﻿using Newtonsoft.Json;
using StackExchange.Redis;
using System;

namespace Common
{
    /// <summary>
    /// redis cache helper
    /// </summary>
    public class RedisCache : ICache, IDisposable
    {

        /// <summary>
        /// 缓存实例名称
        /// </summary>
        private readonly string _instanceName = ConfigHelper.Configuration["Redis:InstanceName"];
        /// <summary>
        /// 缓存服务器
        /// </summary>
        private readonly string _configuration = ConfigHelper.Configuration["Redis:ConnectionString"];
        /// <summary>
        /// 
        /// </summary>
        private readonly int dataBase = 2;
        /// <summary>
        /// 
        /// </summary>
        public RedisCache()
        {
            _connection = ConnectionMultiplexer.Connect(_configuration);
            _cache = _connection.GetDatabase(dataBase);

        }


        private readonly IDatabase _cache;


        private readonly ConnectionMultiplexer _connection;

        private string GetKeyForRedis(string key)
        {
            return _instanceName + key;
        }

        private bool Exists(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            return _cache.KeyExists(GetKeyForRedis(key));
        }


        public void Dispose()
        {
            if (_connection != null)
                _connection.Dispose();
            GC.SuppressFinalize(this);
        }


        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            var value = _cache.StringGet(GetKeyForRedis(key));
            if (!value.HasValue)
                return default(T);


            return JsonConvert.DeserializeObject<T>(value);
        }

        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="key"></param>
        public void Remove(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            _cache.KeyDelete(GetKeyForRedis(key));
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="cache"></param>
        /// <returns></returns>
        public T Set<T>(string key, T cache)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (cache == null)
                throw new ArgumentNullException(nameof(cache));


            if (Exists(GetKeyForRedis(key)))
                Remove(GetKeyForRedis(key));


            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(cache));
            return cache;
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="cache"></param>
        /// <returns></returns>
        public T Set<T>(string key, T cache, DateTimeOffset expiressAbsoulte)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (cache == null)
                throw new ArgumentNullException(nameof(cache));


            if (Exists(GetKeyForRedis(key)))
                Remove(GetKeyForRedis(key));


            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(cache), expiressAbsoulte - DateTime.Now);
            return cache;
        }
    }
}